﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UT3Bots.UTItems;

namespace UT3Bots
{

	#region Event arguments

	public class BotSpawnedEventArgs : EventArgs
	{
		public BotSpawnedEventArgs()
		{

		}
	}

	public class HasDiedEventArgs : EventArgs
	{
		private UTIdentifier _killer;
		private UTIdentifier _killed;

		#region Properties
		/// <summary>
		/// The bot that killed the other one
		/// </summary>
		public UTIdentifier Killer
		{
			get { return _killer; }
		}

		/// <summary>
		/// The bot that died
		/// </summary>
		public UTIdentifier Killed
		{
			get { return _killed; }
		}
		#endregion

		public HasDiedEventArgs(UTIdentifier Killer, UTIdentifier Killed)
		{
			this._killer = Killer;
			this._killed = Killed;
		}
	}

	public class SeenBotEventArgs : EventArgs
	{
		private UTIdentifier _id;
		private string _name;
		private string _team;
		private string _weapon;
		private UTVector _rotation;
		private UTVector _location;
		private UTVector _velocity;
		private bool _isReachable;

		#region Properties
		/// <summary>
		/// The bot that you just saw
		/// </summary>
		public UTIdentifier Id
		{
			get { return _id; }
		}

		/// <summary>
		/// The name of the bot
		/// </summary>
		public string Name
		{
			get { return _name; }
		}

		/// <summary>
		/// The team the bot is on
		/// </summary>
		public string Team
		{
			get { return _team; }
		}

		/// <summary>
		/// The weapon that the bot is currently using
		/// </summary>
		public string Weapon
		{
			get { return _weapon; }
		}

		/// <summary>
		/// The vector that the bot is facing
		/// </summary>
		public UTVector Rotation
		{
			get { return _rotation; }
		}

		/// <summary>
		/// The location of the bot
		/// </summary>
		public UTVector Location
		{
			get { return _location; }
		}

		/// <summary>
		/// The velocity of the bot
		/// </summary>
		public UTVector Velocity
		{
			get { return _velocity; }
		}

		/// <summary>
		/// True if the bot is reachable by running straight to it, False if soemthing is in the way
		/// </summary>
		public bool IsReachable
		{
			get { return _isReachable; }
		}

		#endregion

		public SeenBotEventArgs(UTIdentifier Id, string Name, string Team, string Weapon, UTVector Rotation, UTVector Location, UTVector Velocity, bool IsReachable)
		{
			this._id = Id;
			this._name = Name;
			this._team = Team;
			this._weapon = Weapon;
			this._rotation = Rotation;
			this._location = Location;
			this._velocity = Velocity;
			this._isReachable = IsReachable;
		}
	}

	public class BumpedEventArgs : EventArgs
	{
		private UTIdentifier _id;
		private UTVector _location;
		private UTVector _hitNormal;

		#region Properties
		/// <summary>
		/// The id of the bot that you just bumped
		/// </summary>
		public UTIdentifier Id
		{
			get { return _id; }
		}

		/// <summary>
		/// The location that you just bumped into
		/// </summary>
		public UTVector Location
		{
			get { return _location; }
		}

		/// <summary>
		/// The normal vector between your bot's rotation and that of the bot you bumped
		/// </summary>
		public UTVector HitNormal
		{
			get { return _hitNormal; }
		}
		#endregion

		public BumpedEventArgs(UTIdentifier Id, UTVector Location, UTVector HitNormal)
		{
			this._id = Id;
			this._location = Location;
			this._hitNormal = HitNormal;
		}
	}

	public class HeardSoundEventArgs : EventArgs
	{
		private UTIdentifier _id;
		private UTVector _location;
		private float _loudness;

		#region Properties
		/// <summary>
		/// The id of the thing that made the sound
		/// </summary>
		public UTIdentifier Id
		{
			get { return _id; }
		}

		/// <summary>
		/// The location the sound came from
		/// </summary>
		public UTVector Location
		{
			get { return _location; }
		}

		/// <summary>
		/// How loud the noise was
		/// </summary>
		public float Loudness
		{
			get { return _loudness; }
		}
		#endregion

		public HeardSoundEventArgs(UTIdentifier Id, UTVector Location, float Loudness)
		{
			this._id = Id;
			this._location = Location;
			this._loudness = Loudness;
		}
	}

	public class DamagedEventArgs : EventArgs
	{
		private UTIdentifier _id;
		private UTVector _location;
		private int _damageAmount;
		private string _damageType;
		private UTVector _momentum;

		#region Properties
		/// <summary>
		/// The Id of the thing that damaged you
		/// </summary>
		public UTIdentifier Id
		{
			get { return _id; }
		}

		/// <summary>
		/// The location you were hit from
		/// </summary>
		public UTVector Location
		{
			get { return _location; }
		}

		/// <summary>
		/// The amount of damage you just took
		/// </summary>
		public int DamageAmount
		{
			get { return _damageAmount; }
		}

		/// <summary>
		/// A string describing the type of damage
		/// </summary>
		public string DamageType
		{
			get { return _damageType; }
		}

		/// <summary>
		/// The momentum of the thing that damaged you
		/// </summary>
		public UTVector Momentum
		{
			get { return _momentum; }
		}
		#endregion

		public DamagedEventArgs(UTIdentifier Id, UTVector Location, int DamageAmount, string DamageType, UTVector Momentum)
		{
			this._id = Id;
			this._location = Location;
			this._damageAmount = DamageAmount;
			this._damageType = DamageType;
			this._momentum = Momentum;
		}
	}

	public class ChatEventArgs : EventArgs
	{
		private UTIdentifier _id;
		private string _fromName;
		private bool _isFromTeam;
		private string _message;
		

		#region Properties
		/// <summary>
		/// The Id of the bot that just sent a chat message
		/// </summary>
		public UTIdentifier Id
		{
			get { return _id; }
		}

		/// <summary>
		/// The name of the bot that sent the chat message
		/// </summary>
		public string FromName
		{
			get { return _fromName; }
		}

		/// <summary>
		/// True if the message came from a bot on your team
		/// </summary>
		public bool IsFromTeam
		{
			get { return _isFromTeam; }
		}

		/// <summary>
		/// The message that was sent
		/// </summary>
		public string Message
		{
			get { return _message; }
		}
		#endregion

		public ChatEventArgs(UTIdentifier Id, string FromName, bool IsFromTeam, string Message)
		{
			this._id = Id;
			this._fromName = FromName;
			this._isFromTeam = IsFromTeam;
			this._message = Message;
			
		}
	}

	public class TauntedEventArgs : EventArgs
	{
		private UTIdentifier _id;
		private string _fromName;
		
		#region Properties
		/// <summary>
		/// The Id of the bot that taunted you
		/// </summary>
		public UTIdentifier Id
		{
			get { return _id; }
		}

		/// <summary>
		/// The name of the bot that taunted you
		/// </summary>
		public string FromName
		{
			get { return _fromName; }
		}
		#endregion

		public TauntedEventArgs(UTIdentifier Id, string FromName)
		{
			this._id = Id;
			this._fromName = FromName;
		}
	}

	public class FallEventArgs : EventArgs
	{
		private bool _didFall;
		private UTVector _location;

		#region Properties
		/// <summary>
		/// True if you fell off the ledge, false if you didn't
		/// </summary>
		public bool DidFall
		{
			get { return _didFall; }
		}

		/// <summary>
		/// The location of the ledge
		/// </summary>
		public UTVector Location
		{
			get { return _location; }
		}
		#endregion

		public FallEventArgs(bool DidFall, UTVector Location)
		{
			this._didFall = DidFall;
			this._location = Location;
		}
	}

	public class WeaponChangedEventArgs : EventArgs
	{
		private UTIdentifier _id;
		private string _weaponClass;

		#region Properties
		/// <summary>
		/// The Id of the weapon
		/// </summary>
		public UTIdentifier Id
		{
			get { return _id; }
		}
		/// <summary>
		/// The string describing the class of the weapon
		/// </summary>
		public string WeaponClass
		{
			get { return _weaponClass; }
		}
		#endregion

		public WeaponChangedEventArgs(UTIdentifier Id, string WeaponClass)
		{
			this._id = Id;
			this._weaponClass = WeaponClass;
		}
	}

	public class PickupEventArgs : EventArgs
	{
		private UTItem _item;
		private bool _wasDropped;

		#region Properties
		/// <summary>
		/// The item that you picked up
		/// </summary>
		public UTItem Item
		{
			get { return _item; }
		}

		/// <summary>
		/// True if the item was dropped by someone else, False if it was from a pickup location
		/// </summary>
		public bool WasFromDrop
		{
			get { return _wasDropped; }
		}
		#endregion

		public PickupEventArgs(UTItem Item, bool WasFromDrop)
		{
			this._item = Item;
			this._wasDropped = WasFromDrop;
		}
	}

	public class MatchEndedEventArgs : EventArgs
	{
		private UTIdentifier _winnerId;
		private string _winnerName;
		private string _reason;

		#region Properties
		/// <summary>
		/// The Id of the bot that won the game
		/// </summary>
		public UTIdentifier WinnerId
		{
			get { return _winnerId; }
		}

		/// <summary>
		/// THe name of the bot that won the game
		/// </summary>
		public string WinnerName
		{
			get { return _winnerName; }
		}

		/// <summary>
		/// A string describing the reason they won the match
		/// </summary>
		public string Reason
		{
			get { return _reason; }
		}
		#endregion

		public MatchEndedEventArgs(UTIdentifier WinnerId, string WinnerName, string Reason)
		{
			this._winnerId = WinnerId;
			this._winnerName = WinnerName;
			this._reason = Reason;
		}
	}

	public class PathEventArgs : EventArgs
	{
		private string _id;
		private List<UTNavPoint> _nodes;

		#region Properties
		/// <summary>
		/// The Id that you sent in the GetPath method
		/// </summary>
		public string Id
		{
			get { return _id; }
		}

		/// <summary>
		/// A ordered list of nodes that you must travel to to get to the location you specified in the GetPath call
		/// </summary>
		public List<UTNavPoint> Nodes
		{
			get { return _nodes; }
		}
		#endregion

		public PathEventArgs(string Id, List<UTNavPoint> Nodes)
		{
			this._id = Id;
			this._nodes = Nodes;
		}
	}
	#endregion


	public class BotEvents
	{
		/// <summary>
		/// Occurs when your bot spawns on the map after joining the game, and after dying
		/// </summary>
		public event EventHandler<BotSpawnedEventArgs> OnSpawned;

		/// <summary>
		/// Occurs when your bot is killed
		/// </summary>
		public event EventHandler<HasDiedEventArgs> OnDied;

		/// <summary>
		/// Occurs when another bot somewhere on the map dies
		/// </summary>
		public event EventHandler<HasDiedEventArgs> OnOtherBotDied;

		/// <summary>
		/// Occurs when your bot sees another bot
		/// </summary>
		public event EventHandler<SeenBotEventArgs> OnSeenOtherBot;

		/// <summary>
		/// Occurs when your bot bumps into another bot
		/// </summary>
		public event EventHandler<BumpedEventArgs> OnBumped;

		/// <summary>
		/// Occurs when your bot bumps into a wall
		/// </summary>
		public event EventHandler<BumpedEventArgs> OnBumpedWall;

		/// <summary>
		/// Occurs when your bot hears a noise such as a gun fire, or a bot walking
		/// </summary>
		public event EventHandler<HeardSoundEventArgs> OnHeardNoise;

		/// <summary>
		/// Occurs when your bot is damaged by something
		/// </summary>
		public event EventHandler<DamagedEventArgs> OnDamaged;

		/// <summary>
		/// Occurs when something is said in Chat
		/// </summary>
		public event EventHandler<ChatEventArgs> OnReceivedChat;

		/// <summary>
		/// Occurs when your bot runs into a ledge, if your bot is running, it is likely you have already started to fall
		/// </summary>
		public event EventHandler<FallEventArgs> OnFoundFall;

		/// <summary>
		/// Occurs when someone taunts your bot. Time for revenge!
		/// </summary>
		public event EventHandler<TauntedEventArgs> OnTaunted;

		/// <summary>
		/// Occurs when your bot changes weapon, either from a pickup or because you sent the ChangeWeapon command
		/// </summary>
		public event EventHandler<WeaponChangedEventArgs> OnWeaponChanged;

		/// <summary>
		/// Occurs when your bot picks up an item
		/// </summary>
		public event EventHandler<PickupEventArgs> OnGotPickup;

		/// <summary>
		/// Occurs when the match is over, because some one won or the host ended the game
		/// </summary>
		public event EventHandler<MatchEndedEventArgs> OnMatchEnded;

		/// <summary>
		/// Occurs when the server has calculated a path from your GetPath method
		/// </summary>
		public event EventHandler<PathEventArgs> OnPathReceived;


		private UTBot _utBot;

		public BotEvents(UTBot Bot)
		{
			this._utBot = Bot;
		}

		internal void Trigger_OnSpawned(BotSpawnedEventArgs e)
		{
			if (OnSpawned != null)
			{
				OnSpawned.Invoke(this._utBot, e);
			}
		}

		internal void Trigger_OnDied(HasDiedEventArgs e)
		{
			if (OnDied != null)
			{
				OnDied.Invoke(this._utBot, e);
			}
		}

		internal void Trigger_OnOtherBotDied(HasDiedEventArgs e)
		{
			if (OnOtherBotDied != null)
			{
				OnOtherBotDied.Invoke(this._utBot, e);
			}
		}

		internal void Trigger_OnSeenOtherBot(SeenBotEventArgs e)
		{
			if (OnSeenOtherBot != null)
			{
				OnSeenOtherBot.Invoke(this._utBot, e);
			}
		}

		internal void Trigger_OnBumped(BumpedEventArgs e)
		{
			if (OnBumped != null)
			{
				OnBumped.Invoke(this._utBot, e);
			}
		}

		internal void Trigger_OnBumpedWall(BumpedEventArgs e)
		{
			if (OnBumpedWall != null)
			{
				OnBumpedWall.Invoke(this._utBot, e);
			}
		}

		internal void Trigger_OnHeardNoise(HeardSoundEventArgs e)
		{
			if (OnHeardNoise != null)
			{
				OnHeardNoise.Invoke(this._utBot, e);
			}
		}

		internal void Trigger_OnDamaged(DamagedEventArgs e)
		{
			if (OnDamaged != null)
			{
				OnDamaged.Invoke(this._utBot, e);
			}
		}

		internal void Trigger_OnReceivedChat(ChatEventArgs e)
		{
			if (OnReceivedChat != null)
			{
				OnReceivedChat.Invoke(this._utBot, e);
			}
		}

		internal void Trigger_OnFoundFall(FallEventArgs e)
		{
			if (OnFoundFall != null)
			{
				OnFoundFall.Invoke(this._utBot, e);
			}
		}

		internal void Trigger_OnTaunted(TauntedEventArgs e)
		{
			if (OnTaunted != null)
			{
				OnTaunted.Invoke(this._utBot, e);
			}
		}

		internal void Trigger_OnWeaponChanged(WeaponChangedEventArgs e)
		{
			if (OnWeaponChanged != null)
			{
				OnWeaponChanged.Invoke(this._utBot, e);
			}
		}

		internal void Trigger_OnGotPickup(PickupEventArgs e)
		{
			if (OnGotPickup != null)
			{
				OnGotPickup.Invoke(this._utBot, e);
			}
		}

		internal void Trigger_OnMatchEnded(MatchEndedEventArgs e)
		{
			if (OnMatchEnded != null)
			{
				OnMatchEnded.Invoke(this._utBot, e);
			}
		}

		internal void Trigger_OnPathReceived(PathEventArgs e)
		{
			if (OnPathReceived != null)
			{
				OnPathReceived.Invoke(this._utBot, e);
			}
		}
	}
}
